//==============================================================================
//
//  File        : bsp.c
//  Description : Board support package source code
//  Author      : Jerry Tsao
//  Revision    : 1.0
//
//==============================================================================


#include "includes_fw.h"

#include "reg_retina.h"
#include "lib_retina.h"
//#if WATCHDOG_RESET_EN==1
#include "pcam_msg.h"
//#endif
#include "pcam_api.h"
#include "mmpf_pll.h"
#if (SUPPORT_OSD_FUNC && (MAINTAIN_RTC_TIME_METHOD==USE_HW_TIMER_TRIGGER))
#include "pcam_osd_api.h"
#endif

/** @addtogroup BSP
@{
*/

#define USING_PROTECT_MODE                      //[jerry] for debugger variant


//==============================================================================
//
//                              CONSTANTS
//
//==============================================================================
#define  IRQ_STK_SIZE           256     // entry count
#define  FIQ_STK_SIZE           8

#ifdef ARMUL
MMP_ULONG   TickCtr;
#endif // ARMUL

#define Monitor_Sensor (1 && ESD_RECOVERY)
#define Monitor_Audio (1 && ESD_RECOVERY && SUPPORT_UAC)

//==============================================================================
//
//                              GLOBAL VARIABLES
//
//==============================================================================

MMP_ULONG   *pIRQStkTop;
MMP_ULONG   *pFIQStkTop;

static MMP_ULONG m_systick ;
static MMP_ULONG m_systickclockbase ;


#ifdef ZDW_BARCODE
#include "mmp_reg_gpio.h"
MMP_ULONG m_systick2;
extern MMP_ULONG btnclk;
extern MMP_ULONG m_scntick;
MMP_ULONG m_scned_tick=0;
extern MMP_BOOL bScaning;
//extern MMP_BOOL bTriggering;
//extern MMP_BOOL bAcruiring;
extern MMP_BOOL bBtnPressed;
extern MMP_BOOL bReady;
extern MMP_BOOL bScanned;
extern MMP_BOOL bFirstFrame;
extern MMP_UBYTE uTrueLevel;
extern MMP_BOOL bToSucceedMode;
extern MMP_BOOL bTestMode;
extern int iScanCnt;
#endif


#include "mmp_reg_ibc.h"
//extern volatile AITPS_IBCP pIbcPipeCtl;
//==============================================================================
//
//                              PROTOTYPES
//
//==============================================================================

void  SetStackPointers(void);
#if WATCHDOG_RESET_EN==1
void MMPF_BSP_KickOffWatchDog(void);
#endif

#ifdef ARMUL
void  INT_Initialize(void);
#endif


//------------------------------------------------------------------------------
//  Function    : MMPF_BSP_Initialize
//  Description : Initialize BSP hardware configuration.
//------------------------------------------------------------------------------
unsigned int kSystemTick;

MMP_ERR MMPF_BSP_Initialize(void)
{

    //[jerry] declare 32bit for compiler alignment.
    // 0807 swap array. because FIQ is no used
    static MMP_ULONG    FIQStackPool[FIQ_STK_SIZE];
    static MMP_ULONG    IRQStackPool[IRQ_STK_SIZE];

#ifdef ARMUL
    ARMULPS_INT pINT = ARMULC_BASE_INT;
    ARMULPS_TMR pTMR = ARMULC_BASE_TMR;
#else

#endif // ARMUL

    pIRQStkTop = &IRQStackPool[IRQ_STK_SIZE - 1];
    pFIQStkTop = &FIQStackPool[FIQ_STK_SIZE - 1];

#ifdef ARMUL
    pINT->IRQENSET = 0x00000000;
    pINT->FIQENSET = 0x00000000;
    pTMR->T1CTRL = 0x00000000;
    pTMR->T2CTRL = 0x00000000;
#else
    //AITC_BASE_MC->MC_RCR = 1;                           /* Remap SRAM to 0x00000000                            */
#endif // ARMUL


    MMPF_BSP_InitializeInt();                               // Initialize the interrupt controller
    SetStackPointers();                         /* Initialize the default and exception stacks         */


    //RTNA_Init();

    return MMP_ERR_NONE; //[TBD]
}

//------------------------------------------------------------------------------
//  Function    : MMPF_BSP_InitializeInt
//  Description : Initialize(reset) BSP interrupts
//------------------------------------------------------------------------------

MMP_ERR MMPF_BSP_InitializeInt(void)
{
#ifdef ARMUL
    *ARMULR_INT_IRQENSET = 0x00000000;
    *ARMULR_INT_FIQENSET = 0x00000000;
    INT_Initialize();
#else
    int i;

    AITPS_AIC pAIC = AITC_BASE_AIC;

    RTNA_AIC_IRQ_DisAll(pAIC);                  // Disable ALL interrupts
    RTNA_AIC_IRQ_ClearAll(pAIC);                // Clear ALL interrups if any pending

    #ifdef USING_PROTECT_MODE
    pAIC->AIC_DBR = AIC_DBG_EN;
    #else
    pAIC->AIC_DBR = 0;                          // Disable Protect Mode
    #endif

    for (i = 0; i < 8; i++) {
        RTNA_AIC_IRQ_EOI(pAIC);                 // End of all pending interrupt.
    }
                                                // 0xE51FFF20 is opcode of (ldr pc,[pc,#-0xf20])      */
    *(MMP_ULONG *)0x00000018L = 0xE51FFF20;        // IRQ exception vector - install redirection to AIC   */


#endif // ARMUL

    return MMP_ERR_NONE; //[TBD]
}

//------------------------------------------------------------------------------
//  Function    : MMPF_BSP_InitializeTimer
//  Description : Initialize hardware tick timer interrupt
//------------------------------------------------------------------------------

MMP_ERR MMPF_BSP_InitializeTimer(void)
{
extern MMP_ULONG glCPUFreq;

#ifdef ARMUL
    *ARMULR_TMR_T1LOAD = 0x00002710;                                    // set timer tick 10000 cycle/tick
    *ARMULR_TMR_T1CTRL = ARMULC_TMR_CTRL_EN | ARMULC_TMR_CTRL_PERIOD;   // enable period timer interrupt
    *ARMULR_INT_IRQENSET = 0x00000010;                                  // enable TIMER1 source interrupt
#else
    AITPS_AIC   pAIC = AITC_BASE_AIC;
    AITPS_TC    pTC0 = AITC_BASE_TC0;
    AITPS_TCB   pTCB = AITC_BASE_TCB;
    MMP_ULONG   ulMClk = 0;

    //------------------------------
    // Timer Counter Initialization
    //------------------------------

    // System Timer initialization
    // Initialize TC0 to generate 10000 tick/sec

    MMPF_PLL_GetCPUFreq((MMP_ULONG*)&ulMClk);
  
    #ifdef USING_PROTECT_MODE                       //[jerry] for debugger variant
    RTNA_TC_DBG_En(pTCB);
    #endif

    RTNA_AIC_Open(pAIC, AIC_SRC_TC0, OS_CPU_IRQ_ISR,
                   AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 7);

    #if (CHIP == VSN_V2)
    RTNA_TC_Open(pTC0, TC_CPCTRG | TC_CLK_MCK_D8, 
                    ((ulMClk>>1)*1000/8)/OS_TICKS_PER_SEC);
    #endif
    #if (CHIP == P_V2)
    RTNA_TC_Open(pTC0, TC_CPCTRG | TC_CLK_MCK_D8, 
                    (EXT_CLK*1000/8)/OS_TICKS_PER_SEC);
    #endif

    RTNA_AIC_IRQ_En(pAIC, AIC_SRC_TC0);
    RTNA_TC_SYNC(pTCB);
    RTNA_TC_IRQ_En(pTC0, TC_CPCS);

#ifdef ZDW_BARCODE
	m_systick2 = 0;
#else
    m_systick = 0 ;
#endif
    m_systickclockbase = glCPUFreq / pTC0->TC_RC ;
#endif // ARMUL


    return MMP_ERR_NONE; //[TBD]
}

#if Monitor_Audio
extern MMP_USHORT USB_AudioReset(MMP_USHORT nonblocking);
static MMP_ULONG glaudiotick = 0;
#endif
#if Monitor_Sensor	
static MMP_ULONG glsensortick = 0;
#endif
static MMP_ULONG gltimertick = 0;
MMP_ULONG gltickcount = 1000;
MMP_UBYTE gbsensortick_enable = 0;

extern MMP_ULONG glviftick;
extern MMP_ULONG glI2Stick;
extern MMP_UBYTE glAudioEnable;

#if ESD_RECOVERY
MMP_UBYTE gbSensorReInitFlag = 0;
#endif
//------------------------------------------------------------------------------
//  Function    : MMPF_BSP_TimerHandler
//  Description : BSP tick timer interrupt handler
//------------------------------------------------------------------------------
MMP_ERR MMPF_BSP_TimerHandler(void)
{
#if HEARTBEAT_LED_EN==1
extern MMP_USHORT USB_CheckTaskAlive(MMP_USHORT heartbeat);

static MMP_ULONG ind_bl2_toggle = 0;
static MMP_UBYTE ind_bl2_on_off = 0 ;
#endif

    AITPS_AIC   pAIC = AITC_BASE_AIC;
    AITPS_TC    pTC0 = AITC_BASE_TC0;
#if (CUSTOMER == PNS)
extern MMP_UBYTE POP_UP_LOOP,POP_Up_Cycle;
#endif
    m_systick++;
#if 0//def ZDW_BARCODE
	m_systick2++;
 
	if(bReady&&!bToSucceedMode&&!bTestMode){
		//MMP_UBYTE uLevel;
		AITPS_GPIO  pGPIO = AITC_BASE_GPIO;
		uTrueLevel = (pGPIO->GPIO_DATA[1]&0x100)>>8;

		if((m_systick%50) == 0){
			if((uTrueLevel == 0)&&!bBtnPressed){
				bBtnPressed = TRUE;
#ifndef TEST_FOR_PRODUCTION				
				iScanCnt = 0;
#endif
				TriggerScan();
			}else if(uTrueLevel == 1){
				bBtnPressed = FALSE;
				bScanned = FALSE;
				bFirstFrame = FALSE;
				//bAcruiring = FALSE;
				bScaning = FALSE;
				Turn_On_Off_W_LED(FALSE);
				Turn_On_Off_R_LED(FALSE);
			}//else if(bBtnPressed&&bScaning){
			//	if((m_systick - m_scntick)>300)
			//		Turn_On_Off_R_LED(FALSE);
			//}
		}
	}
#endif   
    OSTimeTick();                       //  call OSTimeTick()
	kSystemTick  += (1000 / OS_TICKS_PER_SEC);
    #if OS_TMR_EN > 0
    OSTmrSignal();
    #endif

    #ifdef USING_PROTECT_MODE
    pAIC->AIC_IVR = 0x0;                // Write IVR to end interrupt (protect mode used)
    #endif

#if (SUPPORT_OSD_FUNC && (MAINTAIN_RTC_TIME_METHOD==USE_HW_TIMER_TRIGGER))
    {
        extern MMP_USHORT nPcamOsdTimerCount;
        extern MMP_UBYTE gbOSDTimeFormatChange, gbOSDWordCntChange;
        nPcamOsdTimerCount++;
        if(nPcamOsdTimerCount >= 1000){
            nPcamOsdTimerCount = 0;
            pcam_RTC_UpdateTime();
        }
        else if(gbOSDTimeFormatChange == 1){
            gbOSDTimeFormatChange = 0;
            gbOSDWordCntChange = 1;
            pcam_RTC_UpdateTimeString();
        }
    }
#endif

	++gltimertick;
	gltimertick %= gltickcount;

#if Monitor_Sensor	
	if(gbsensortick_enable && (gltimertick == 0)){
#if ESD_RECOVERY
		if((glsensortick == glviftick) || gbSensorReInitFlag)
#else
		if(glsensortick == glviftick)
#endif
		{
			gltickcount = 5000;
#if ESD_RECOVERY
			gbSensorReInitFlag = 0;
#endif
			MMPF_USBCTL_PostMsg(2,TASK_USB_PRIO,USBCTL_MSG_RESET_SENSOR,0,(void *)NULL);
		}else
			gltickcount = 1000;

        //dbg_printf(3,"glviftick: %d, glsensortick: %d\r\n",glviftick, glsensortick);
		
		glsensortick = glviftick;
	}
#endif

#if (CUSTOMER == PNS)
		if ((POP_UP_LOOP==1)&&(gltimertick == 0))
		{
			MMPF_USBCTL_PostMsg(2,TASK_USB_PRIO,USBCTL_MSG_POPUP_LOOP,0,(void *)NULL);
			gltickcount = (POP_Up_Cycle * 1000) - 100;
		}
#endif

#if Monitor_Audio
	if(glAudioEnable && (gltimertick == 0)){
		if(glaudiotick == glI2Stick){
			gltickcount = 10000;
			USB_AudioReset(PCAM_NONBLOCKING);
		}else
			gltickcount = 1000;

        //dbg_printf(3,"glI2Stick: %d, glaudiotick: %d\r\n",glI2Stick, glaudiotick);
		
		glaudiotick = glI2Stick;
	}
#endif

    #if HEARTBEAT_LED_EN==1
    if( !(ind_bl2_toggle & 0x3FF) ) {
        //USB_LEDDisplay(TEST_PIN1, ind_bl2_on_off & 1 ) ;
//        USB_CheckTaskAlive(ind_bl2_on_off & 1 );
        ind_bl2_on_off++;
    }
    ind_bl2_toggle++;
    #endif
    #if WATCHDOG_RESET_EN
    MMPF_BSP_KickOffWatchDog();
    #endif
    
    RTNA_TC_SR_Clear(pTC0);            // clear interrupt status register
    pAIC->AIC_ICCR = 0x1 << AIC_SRC_TC0;    // Disable TC0 Interrupt on AIC

    pAIC->AIC_EOICR = 0x0;        // End of interrupt handler

    return MMP_ERR_NONE;
}

#if SUPPORT_AIT845x_MD
void MD_printk(char *fmt, ...)
{
    dbg_printf(3, fmt);
    dbg_printf(3, "\r");
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_BSP_IntHandler
//  Description : BSP interrupt handler
//------------------------------------------------------------------------------

MMP_ERR MMPF_BSP_IntHandler(void)
{
    return	MMPF_BSP_TimerHandler();
}

/** @brief Get OS tick number
@retval system tick
@note Return in tick, not in ms.
*/
MMP_ULONG MMPF_BSP_GetTick(void)
{
    return m_systick;
}

/** @brief Get CPU counter for the OS tick timer.

This would be the fractional part. The clock shall be reset after trigger the Timer ISR.
@retval The clock of the OS tick timer
*/
MMP_ULONG MMPF_BSP_GetTickClock(void)
{
    AITPS_TC pTC0 = AITC_BASE_TC0 ;
    return pTC0->TC_CVR * m_systickclockbase ;
}

#if WATCHDOG_RESET_EN==1
void MMPF_BSP_KickOffWatchDog(void)
{
#define WATCHDOG_CLEAN_PERIOD (200) // clean watchdog timer by 200 ms period
extern MMPF_OS_FLAGID PCAM_Flag ;
static int watchdog_period = 0 ;    
    watchdog_period++ ;
    if(watchdog_period>=WATCHDOG_CLEAN_PERIOD) {
        MMPF_OS_SetFlags(PCAM_Flag, PCAM_FLAG_WATCHDOG, MMPF_OS_FLAG_SET);
        watchdog_period = 0; 
    }

}
#endif

/** @} */ // end of BSP
/** @} */ // end of BSP